library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;

-- Unité de multiplication dans l'espace numérique de Montgomery (dite MMU)
-- Actuellement purement combinatoire


---------------------

entity Mult_Montg_Unit is
  
generic(
	Z : positive range 1 to 256 ;		-- Nombre de bits du module
	N : positive ;	-- Vecteur de base utilisé
	R : positive ;	-- Plus proche puissance de 2 de N par valeur supérieure
	log2R : positive ; 
	k : positive 	-- Constante nécessaire au calcul
) ;
port (
	a : in std_logic_vector(Z-1 downto 0) ;	-- Entrée 1 multiplicateur (domaine de Montgomery)
	b : in std_logic_vector(Z-1 downto 0) ;	-- Entrée 2 multiplicateur (domaine de Montgomery)
	is_active : in std_logic ;		-- La MMU doit-elle fonctionner?
	
	clk : in std_logic ;	-- Signal d'horloge
	reset : in std_logic;
	
	c : out std_logic_vector(Z-1 downto 0) ;	-- Sortie du multiplicateur (domaine de Montgomery)
	is_ready : out std_logic ;		-- La MMU est-elle prête à fonctionner?
	is_end : out std_logic		-- La MMU a-t-elle fini?
) ;
end entity ;


---------------------




architecture MMU_V1 of Mult_Montg_Unit is
	
	signal c_temp : std_logic_vector(8*Z-1 downto 0) ;

     


      --  function mod2n (A, R_unsigned : unsigned, pn : integer) return unsigned is
      --  begin
      --   	return resize(A(Z-1-k downto 0),Z);
      --  end mod2n;


begin
	is_ready <= '1' ;
	is_end <= '1' ;
	

        
	
	process( a, b )
	
	variable sto1 : unsigned(2*Z-1 downto 0) ;
	variable sto2 : unsigned(8*Z-1 downto 0) ;
	
	begin
	
		sto1 := unsigned(A) * unsigned(B) ;
		sto2 := resize( sto1(log2R downto 0), 8*Z ) ;
		sto2 := resize( ( sto2 * k ), 8*Z ) ;
		sto2 := resize( sto2(log2R downto 0), 8*Z) ;
		sto2 := resize( ( sto2 * N + sto1), 8*Z) ;
		sto2 := resize( sto2(8*Z-1 downto log2R), 8*Z) ;
		
		if ( sto2 > N ) then
			sto2 := sto2 - N ;
		else
			sto2 := sto2 ; 
		end if ;
		
		c_temp <= std_logic_vector(sto2);     
	
	end process ;
	
	c <= c_temp(z-1 downto 0) ;
  
end MMU_V1 ;




